> How does one code a suid program so that it evades these problems > with symlink race conditions? "Vewy, vewy cawefuwwy." Setuid programs should always be coded very carefully. Programs that have to be race-immune _must_ be coded very carefully. Programs that are both (which includes many/most setuid programs) require even more extreme care. It helps if you've done parallel code, because it helps develop the necessary discipline of thinking of worst-case races. > Is there a way to atomically check if a file is a symlink and open > it, or is there another stratedgy? Sort of. The following might be sufficiently paranoid to be generally safe. (Note: I said "might be", not "is".) To open a file, which should already exist: - lstat() the path, check that lstat succeeded - check that it's acceptable (eg, not a symlink :-) - open() (without O_CREAT), check that the open succeeded - fstat() the fd returned by open - if the lstat and fstat st_ino and st_dev fields match, accept. To create a new file, which doesn't already exist: - lstat() the path, check that you got ENOENT - open(...,...|O_CREAT|O_EXCL,...), check that it succeeded If you're really paranoid, then: - fstat() the fd returned by open - lstat() the path again, check that (a) it exists and (b) isn't a symlink - check that the fstat and the last lstat returned matching st_dev and st_ino fields Note that the latter depends on the O_CREAT|O_EXCL semantics of not following a trailing symlink. I would have preferred an O_NOSYMLINK bit, myself, but oh well. der Mouse mouse@collatz.mcrcim.mcgill.edu